import os
import zipfile

from lxml import etree


def resize_images_in_large_docx(doc_path, new_width_cm):
    # 创建一个临时文件来存储修改后的 document.xml
    temp_doc_path = doc_path + '.temp'

    # 打开文档
    with zipfile.ZipFile(doc_path, 'r') as zip_ref:
        # 读取 [Content_Types].xml 文件
        content_types_xml = zip_ref.read('[Content_Types].xml')
        content_types_tree = etree.fromstring(content_types_xml)

        # 读取 document.xml 文件
        document_xml = zip_ref.read('word/document.xml')
        document_tree = etree.fromstring(document_xml)

        # 遍历所有的图片
        for blip in document_tree.xpath('.//a:blip',
                                        namespaces={'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'}):
            blip_id = blip.get('{http://schemas.openxmlformats.org/officeDocument/2006/relationships}embed')

            # 获取图片的宽度和高度
            xfrm = blip.getparent().getparent().getparent().find('.//a:xfrm', namespaces={
                'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'})
            ext = xfrm.find('.//a:ext', namespaces={'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'})
            cx = int(ext.get('cx'))
            cy = int(ext.get('cy'))

            # 计算新的宽度（单位：厘米）
            new_width_emu = int(new_width_cm * 360000)  # 1 厘米 = 360000 EMU

            # 设置新的宽度
            ext.set('cx', str(new_width_emu))

            # 如果需要保持宽高比，计算新的高度
            aspect_ratio = cy / cx
            new_height_emu = int(new_width_emu * aspect_ratio)
            ext.set('cy', str(new_height_emu))

        # 将修改后的 document.xml 写入临时文件
        with open(temp_doc_path, 'wb') as temp_file:
            with zipfile.ZipFile(temp_file, 'w') as temp_zip:
                # 写入 [Content_Types].xml
                temp_zip.writestr('[Content_Types].xml', etree.tostring(content_types_tree))

                # 写入修改后的 document.xml
                temp_zip.writestr('word/document.xml', etree.tostring(document_tree))

                # 复制其他文件
                for item in zip_ref.infolist():
                    if item.filename not in ['[Content_Types].xml', 'word/document.xml']:
                        temp_zip.writestr(item.filename, zip_ref.read(item))

    # 替换原始文件
    os.replace(temp_doc_path, doc_path)


# 使用示例
doc_path = 'D:\opt\zpj.docx'
new_width_cm = 10  # 新宽度（厘米）
resize_images_in_large_docx(doc_path, new_width_cm)
